using System;
using System.Text;
using System.Collections.Generic;

namespace AntiXssExperimental {
public class Utf8Decoder
{
static int Bits(int m, int n, int c){return ((c >> n) & ~(-2 << (m - n)));}

public static string Apply(string input){
var output = new StringBuilder(input.Length >= 16384 ? input.Length : (int)(Math.Min(16384, (long)input.Length * 1)));
int r0 = 0;int state = 0;
for (int i = 0; i < input.Length; i++){
int c = (int)input[i];
switch (state){
case (0): {
  if ((Bits(15,7,c)==0)) {
    output.Append((char)c);
    r0 = 0;
    state = 0;
  } else {
    if (((0xC2<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xDF))) {
      r0 = (Bits(5,0,c)<<6);
      state = 1;
    } else {
      if ((c==0xE0)) {
        r0 = 0;
        state = 2;
      } else {
        if ((c==0xED)) {
          r0 = 0;
          state = 3;
        } else {
          if ((((0xE1<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xEC))||((0xEE<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xEF)))) {
            r0 = (Bits(3,0,c)<<12);
            state = 4;
          } else {
            if (((0xF1<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xF3))) {
              r0 = (Bits(2,0,c)<<8);
              state = 5;
            } else {
              if ((c==0xF0)) {
                r0 = 0;
                state = 6;
              } else {
                if ((c==0xF4)) {
                  r0 = 0;
                  state = 7;
                } else {
                  throw new Exception("InvalidInput");
                }
              }
            }
          }
        }
      }
    }
  }
break;}
case (7): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0x8F))) {
    r0 = ((0xFFC0+((0x10|Bits(5,4,c))<<6))|(Bits(3,0,c)<<2)|0xD800);
    state = 8;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (8): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    output.Append((char)(r0|Bits(5,4,c)));
    r0 = ((0x370|Bits(3,0,c))<<6);
    state = 1;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (6): {
  if (((0x90<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    r0 = ((0xFFC0+(Bits(5,4,c)<<6))|(Bits(3,0,c)<<2)|0xD800);
    state = 8;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (5): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    r0 = ((0xFFC0+(r0|(Bits(5,4,c)<<6)))|(Bits(3,0,c)<<2)|0xD800);
    state = 8;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (4): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    r0 = (r0|(Bits(5,0,c)<<6));
    state = 1;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (3): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0x9F))) {
    r0 = ((0x340|Bits(5,0,c))<<6);
    state = 1;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (2): {
  if (((0xA0<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    r0 = (Bits(5,0,c)<<6);
    state = 1;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
case (1): {
  if (((0x80<=c)&&(Bits(15,8,c)==0)&&(Bits(7,0,c)<=0xBF))) {
    output.Append((char)(r0|Bits(5,0,c)));
    r0 = 0;
    state = 0;
  } else {
    throw new Exception("InvalidInput");
  }
break;}
default: {
  throw new Exception("Utf8Decoder");
}
}
}
switch (state){
case (0): {
break;}
case (7): {
  throw new Exception("InvalidInput");
break;}
case (8): {
  throw new Exception("InvalidInput");
break;}
case (6): {
  throw new Exception("InvalidInput");
break;}
case (5): {
  throw new Exception("InvalidInput");
break;}
case (4): {
  throw new Exception("InvalidInput");
break;}
case (3): {
  throw new Exception("InvalidInput");
break;}
case (2): {
  throw new Exception("InvalidInput");
break;}
case (1): {
  throw new Exception("InvalidInput");
break;}
default: {
  throw new Exception("Utf8Decoder");
}
}
return output.ToString();
}
}
}
